home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / New System Software Extensions / OpenDoc A6 / OpenDoc Parts Framework / OPF / Found / FWDebug / Sources / FWTrace.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-21  |  13.9 KB  |  440 lines  |  [TEXT/MPS ]

  1. #if defined(FW_DEBUG)
  2. // This entire file is for debugging only
  3. //========================================================================================
  4. //
  5. //    File:                FWTrace.cpp
  6. //    Release Version:    $ 1.0d1 $
  7. //
  8. //    Creation Date:        3/28/94
  9. //
  10. //    Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  11. //
  12. //========================================================================================
  13.  
  14. #ifndef   FWTRACE_H
  15. #include "FWTrace.h"
  16. #endif
  17.  
  18. #ifndef   FWPRIDEB_H
  19. #include "FWPriDeb.h"
  20. #endif
  21.  
  22. #ifndef   FWPRISTR_H
  23. #include "FWPriStr.h"
  24. #endif
  25.  
  26. #ifndef   FWPRIMEM_H
  27. #include "FWPriMem.h"
  28. #endif
  29.  
  30. #ifdef FW_BUILD_MAC
  31.  
  32. #include <StdDef.h>
  33. #include <LowMem.h>
  34.  
  35. #endif
  36.  
  37. #if defined(FW_BUILD_WIN) && !defined(FWSYMFIL_H)
  38. #include "FWSymFil.h"
  39. #endif
  40.  
  41. #if defined(FW_BUILD_WIN) && !defined(FWWTRACE_H)
  42. #include "FWWTrace.h"
  43. #endif
  44.  
  45. #ifdef __ZTC__
  46. #include <stdlib.h>
  47. extern "C"
  48. {
  49.     char* unmangle_ident(const char* ident);
  50. };
  51. #endif
  52.  
  53. //========================================================================================
  54. // CLASS FW_CTraceRuntime
  55. //========================================================================================
  56.  
  57. char FW_CTraceRuntime::gPrefixChar[2] = {'>', '<'};
  58.  
  59. //----------------------------------------------------------------------------------------
  60. // FW_CTraceRuntime::Initialize
  61. //----------------------------------------------------------------------------------------
  62. short FW_CTraceRuntime::Initialize(FW_CDebugStream *traceStream)
  63. {
  64.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  65.     short successful = 0;
  66.     
  67.     globals.gTraceEnabled = 0;
  68.     
  69.     if (traceStream != NULL)
  70.     {
  71.         globals.gTraceStream = traceStream;
  72. #ifdef FW_BUILD_WIN16
  73.         void* pTraceBuffer = ::FW_PrimitiveAllocateBlock(32000);
  74.         FW_PRIV_ASSERT(pTraceBuffer != NULL);
  75.         globals.gTraceBuffer = pTraceBuffer;
  76.         successful = pTraceBuffer != NULL;
  77.         
  78.         FW_CPrivWinDebugModuleList::Initialize();
  79. #endif
  80.     }
  81.     
  82.     return successful;
  83. }
  84.  
  85. //----------------------------------------------------------------------------------------
  86. // FW_CTraceRuntime::Terminate
  87. //----------------------------------------------------------------------------------------
  88. void FW_CTraceRuntime::Terminate()
  89. {
  90.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  91.     globals.gTraceStream = NULL;
  92. #ifdef FW_BUILD_WIN16
  93.     ::FW_PrimitiveFreeBlock(globals.gTraceBuffer);
  94.     globals.gTraceBuffer = NULL;
  95.  
  96.     FW_CPrivWinDebugModuleList::Terminate();
  97. #endif
  98. }
  99.  
  100. //----------------------------------------------------------------------------------------
  101. // FW_CTraceRuntime::StartTrace
  102. //----------------------------------------------------------------------------------------
  103. // We increment the counter each time StartTrace is called.
  104. // Tracing is only enabled when the counter is above 0.
  105. void FW_CTraceRuntime::StartTrace()
  106. {
  107.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  108.     unsigned short enableCount = globals.gTraceEnabled;
  109.     enableCount++;
  110.     FW_PRIV_ASSERT(enableCount>0);    // if fails, StartTrace called too many times!
  111.     globals.gTraceEnabled = enableCount;
  112. }
  113.  
  114. //----------------------------------------------------------------------------------------
  115. // FW_CTraceRuntime::StopTrace
  116. //----------------------------------------------------------------------------------------
  117. void FW_CTraceRuntime::StopTrace()
  118. {
  119.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  120.     unsigned short enableCount = globals.gTraceEnabled;
  121.     FW_PRIV_ASSERT(enableCount>0);    // if fails, StopTrace called too many times!
  122.     enableCount--;
  123.     globals.gTraceEnabled = enableCount;
  124. }
  125.  
  126. //========================================================================================
  127. // Windows specific functions
  128. //========================================================================================
  129.  
  130. //----------------------------------------------------------------------------------------
  131. // FW_CTraceRuntime::TraceIn
  132. //----------------------------------------------------------------------------------------
  133. //    Called every time a function is entered
  134. #ifdef FW_BUILD_WIN16
  135. void FW_CTraceRuntime::TraceIn()
  136. {
  137.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  138.     unsigned short enableCount = globals.gTraceEnabled;
  139.     if (enableCount == 0)
  140.         return;
  141.  
  142.     void* pTraceBuffer = globals.gTraceBuffer;
  143.     FW_CDebugStream * traceStream = globals.gTraceStream;
  144.  
  145.     if (pTraceBuffer != NULL && traceStream != NULL)
  146.     {
  147.         // Walk the stack
  148.         HANDLE hModule;
  149.         WORD wSegment;
  150.         WORD wOffset;
  151.  
  152.         FW_PrivWinGetCallerInfo(&hModule, NULL, &wSegment, &wOffset, 3);
  153.         
  154.         DumpOneLine(*traceStream, ">> ", hModule, wSegment, wOffset);
  155.         
  156.         WORD * pwTraceBuffer = (WORD *)pTraceBuffer;
  157.         *pwTraceBuffer++ = wSegment;
  158.         *pwTraceBuffer++ = wOffset;
  159.         *pwTraceBuffer++ = hModule;
  160.         globals.gTraceBuffer = pwTraceBuffer;
  161.     }
  162. }
  163. #endif
  164.  
  165. //----------------------------------------------------------------------------------------
  166. // FW_CTraceRuntime::TraceOut
  167. //----------------------------------------------------------------------------------------
  168. //    Called every time a function is exited
  169. #ifdef FW_BUILD_WIN16
  170. void FW_CTraceRuntime::TraceOut()
  171. {
  172.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  173.     unsigned short enableCount = globals.gTraceEnabled;
  174.     if (enableCount == 0)
  175.         return;
  176.  
  177.     void* pTraceBuffer = globals.gTraceBuffer;
  178.     FW_CDebugStream * traceStream = globals.gTraceStream;
  179.  
  180.     if (pTraceBuffer != NULL && traceStream != NULL)
  181.     {
  182.         // Walk the stack
  183.         HANDLE hModule;
  184.         WORD wSegment;
  185.         WORD wOffset;
  186.  
  187.         WORD * pwTraceBuffer = (WORD *)pTraceBuffer;
  188.         hModule = *--pwTraceBuffer;
  189.         wOffset = *--pwTraceBuffer;
  190.         wSegment = *--pwTraceBuffer;
  191.         globals.gTraceBuffer = pwTraceBuffer;
  192.  
  193.         DumpOneLine(*traceStream, "<< ", hModule, wSegment, wOffset);
  194.     }
  195. }
  196. #endif
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // FW_CTraceRuntime::DumpOneLine
  200. //----------------------------------------------------------------------------------------
  201. #ifdef FW_BUILD_WIN16
  202. void FW_CTraceRuntime::DumpOneLine(FW_CDebugStream& traceStream,
  203.                              const char* pzPrefix,
  204.                              unsigned hModule,
  205.                              unsigned wSegment,
  206.                              unsigned wOffset)
  207. {
  208.     int fSymbolFound=0, fModuleFound=0;
  209.     char zSymbol[128];
  210.     char zModule[10];
  211.  
  212.     fModuleFound = FW_CPrivWinDebugModuleList::GetModuleName(hModule, zModule);
  213.     fSymbolFound = FW_CPrivWinDebugModuleList::FindSymbol(hModule, wSegment, wOffset, sizeof zSymbol, zSymbol);
  214.  
  215. #ifdef __ZTC__
  216.     if(fSymbolFound)
  217.     {
  218.         char* pzUnm = unmangle_ident(zSymbol);
  219.         if(pzUnm)
  220.         {
  221.             FW_PrimitiveStringCopy(zSymbol, pzUnm);
  222.             ::free(pzUnm);
  223.         }
  224.     }
  225. #endif
  226.  
  227.     traceStream << pzPrefix << " ";
  228.     traceStream << (fModuleFound ? (char *) zModule : "?") << ": ";
  229.     traceStream << ((void*) wSegment) << ":" << ((void*) wOffset) << " ";
  230.     traceStream << (fSymbolFound ? (char *) zSymbol : "?") << EndLine;
  231. }
  232. #endif
  233.  
  234.  
  235. //========================================================================================
  236. // Macintosh specific functions
  237. //========================================================================================
  238.  
  239. // Disable tracing so that we don't end up doing a circular trace in this code. 
  240. //   This code has been placed at the end of the file so that the rest of the
  241. //   runtime library can be traced if necessary.
  242. #pragma trace off
  243.  
  244. //----------------------------------------------------------------------------------------
  245. // GetCurStackBase
  246. //----------------------------------------------------------------------------------------
  247. //    Returns a pointer to the current stack base.  This routine is used for sanity 
  248. //    checking functions being traced.  If the PC goes beyond the stackbase, 
  249. //    then something is wrong.
  250. #ifdef FW_BUILD_MAC
  251. inline void* GetCurStackBase()
  252. {
  253.     return *((void**)LMGetCurStackBase());
  254. }
  255. #endif
  256.  
  257. //----------------------------------------------------------------------------------------
  258. // GetCurStackFramePtr
  259. //----------------------------------------------------------------------------------------
  260. //    Returns a pointer to the current stack frame.  This function is used to determine 
  261. //    the return address for the function.
  262. #ifdef FW_BUILD_MAC
  263. pascal Ptr GetCurStackFramePtr() = {0x2e8e};
  264. #endif
  265.  
  266.  
  267. //----------------------------------------------------------------------------------------
  268. // GetReturnAddress
  269. //----------------------------------------------------------------------------------------
  270. //    Returns a pointer to the return address of the function being traced.  This address 
  271. //    is then used to find the function name, which is stored at the end of the function.
  272. #ifdef FW_BUILD_MAC
  273. inline void* GetReturnAddress(Ptr FramePtr)
  274. {
  275.     return (*(void **) ((long)FramePtr + 4));
  276. }
  277. #endif
  278.  
  279. //----------------------------------------------------------------------------------------
  280. // odd - returns TRUE if value is an odd number, otherwise returns FALSE.
  281. //----------------------------------------------------------------------------------------
  282. #ifdef FW_BUILD_MAC
  283. inline Boolean odd(long value)
  284. {
  285.     return (value & 0x00000001);
  286. }
  287. #endif
  288.  
  289. //----------------------------------------------------------------------------------------
  290. // GetProcName
  291. //----------------------------------------------------------------------------------------
  292. //    Returns the name of the procedure or function in which pc points. If it is in a 
  293. //    method, then it return"s the name of the method"s class in className.  procName is 
  294. //    assumed to be at least 255 characters.
  295. #ifdef FW_BUILD_MAC
  296. pascal void GetProcName(void* pc, char* procName)
  297. {
  298.     procName[0] = '\0';
  299. #ifdef _MPWCFRONT
  300. // (MLH) ??? Need to have a symantec C++ implementation of this. Especially
  301. // since we don't use mpw cfront anymore.
  302.  
  303. if (pc != NULL && !odd((long) pc))
  304.     {
  305.         void* nextPC;
  306.         char localProcName[256];
  307.  
  308.         // Get the routine name from the end of the module that was
  309.         //  entered.  localProcName will contain a null-terminated
  310.         //  pascal string containing the mangled name.
  311.         Ptr limit = (Ptr) ((ptrdiff_t) pc + 32767);
  312.         while (!endOfModule(pc, limit, localProcName, &nextPC))
  313.         {
  314.             if (pc >= limit)
  315.             {
  316.                 procName[0] = '\0';
  317.                 localProcName[0] = '\0';
  318.                 return;
  319.             }
  320.             else
  321.                 pc = (void *) ((ptrdiff_t) pc + 2);
  322.         }
  323.  
  324.         char cProcName[256];
  325.  
  326.         // unmangle the localProcName to something more recognizable,
  327.         //  then put it in procName.
  328.         if (unmangle(cProcName, &(localProcName[1]), 255) < 1)
  329.             FW_PrimitiveStringCopy(procName, &(localProcName[1]));
  330.         else
  331.             FW_PrimitiveStringCopy(procName, cProcName);
  332.     }
  333. #endif
  334. }
  335. #endif
  336.  
  337. //----------------------------------------------------------------------------------------
  338. // TraceIn
  339. //----------------------------------------------------------------------------------------
  340. //    Called when a routine is entered.  Writes the routine name out to the current logfile.
  341. //    If no logfile exists, then nothing happens.
  342. #ifdef FW_BUILD_MAC
  343. void FW_CTraceRuntime::TraceIn()
  344. {
  345.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  346.     IncrTraceDepth();
  347.     unsigned short enableCount = globals.gTraceEnabled;
  348.     if (enableCount > 0)
  349.     {
  350.         FW_CDebugStream* traceStream = globals.gTraceStream;
  351.         
  352.         if (traceStream != NULL)
  353.         {    
  354.             char        procName[256];
  355.             void*         returnAddress = GetReturnAddress(GetCurStackFramePtr());
  356.             
  357.             GetProcName(returnAddress, procName);
  358.     
  359.             DumpOneLine(*traceStream, globals.gTraceDepth, kStepIn, procName);
  360.         }
  361.     }
  362.  
  363. }
  364. #endif
  365.  
  366. //----------------------------------------------------------------------------------------
  367. // TraceOut
  368. //----------------------------------------------------------------------------------------
  369. //    Called when a routine is exited.  Writes the routine name out to the current logfile.
  370. //    If no logfile exists, then nothing happens.
  371. #ifdef FW_BUILD_MAC
  372. void FW_CTraceRuntime::TraceOut()
  373. {
  374.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  375.     unsigned short enableCount = globals.gTraceEnabled;
  376.     if (enableCount > 0)
  377.     {
  378.         FW_CDebugStream* traceStream = globals.gTraceStream;
  379.         
  380.         if (traceStream != NULL)
  381.         {
  382.             void*    curStackFrame = GetReturnAddress(GetCurStackFramePtr());
  383.             char     procName[256];
  384.             
  385.             GetProcName(curStackFrame, procName);
  386.     
  387.             DumpOneLine(*traceStream, globals.gTraceDepth, kStepOut, procName);
  388.         }
  389.     }
  390.     DecrTraceDepth();
  391. }
  392. #endif
  393.  
  394. //----------------------------------------------------------------------------------------
  395. // DumpOneLine
  396. //----------------------------------------------------------------------------------------
  397. //    Writes the strings pzPrefix and procName out to the file specified by traceStream.  
  398. //    traceStream must point to a valid file.  pzPrefix is used by TraceIn and TraceOut to 
  399. //    determine whether a function is being entered or exited.  procName contains the 
  400. //    name of the function being entered or exited.
  401. #ifdef FW_BUILD_MAC
  402. void FW_CTraceRuntime::DumpOneLine(FW_CDebugStream& traceStream,
  403.                                   unsigned short depth,
  404.                                   StepInOut direction,
  405.                                   const char* procName)
  406. {
  407.     const unsigned short maxIndentDepth=20;
  408.     if (depth > maxIndentDepth)
  409.         depth = maxIndentDepth;
  410.     for (short i=0; i<depth; i++)
  411.         traceStream << gPrefixChar[direction];
  412.     traceStream << procName << EndLine;
  413. }
  414. #endif
  415.  
  416. //----------------------------------------------------------------------------------------
  417. // FW_CTraceRuntime::IncrTraceDepth
  418. //----------------------------------------------------------------------------------------
  419. #ifdef FW_BUILD_MAC
  420. void FW_CTraceRuntime::IncrTraceDepth()
  421. {
  422.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  423.     globals.gTraceDepth++;
  424.     FW_PRIV_ASSERT(globals.gTraceDepth>0);    // if fails, IncrTraceDepth called too many times!
  425. }
  426. #endif
  427.  
  428. //----------------------------------------------------------------------------------------
  429. // FW_CTraceRuntime::DecrTraceDepth
  430. //----------------------------------------------------------------------------------------
  431. #ifdef FW_BUILD_MAC
  432. void FW_CTraceRuntime::DecrTraceDepth()
  433. {
  434.     FW_SPrivTraceGlobals& globals = FW_CPrivTraceTaskGlobals::GetTraceGlobals();
  435.     globals.gTraceDepth--;
  436.     FW_PRIV_ASSERT(globals.gTraceDepth>=0);    // if fails, DecrTraceDepth called too many times!
  437. }
  438. #endif
  439.  
  440. #endif